/**
 * 
 */
package com.binary.quartz;

import java.util.Date;
import java.util.List;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;

import com.binary.entity.Quartz;
import com.binary.service.QuartzService;

/**
 * @author dbinary
 * @date 2018年7月21日 上午11:15:46 
 * function:quartz DI
 */

public class QuartzBeanFactory implements ApplicationContextAware {

	private ApplicationContext applicationContext;

	private Scheduler schedule;
	
	private static Logger logger  = LoggerFactory.getLogger(QuartzBeanFactory.class);
	@Autowired
	private QuartzService quartzService;

	public void setSchedule(Scheduler schedule) {
		this.schedule = schedule;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicatonContext) throws BeansException {
		this.applicationContext = applicatonContext;
		setCronBeanIntoSchedule();
	}

	/**
	 * 
	 */
	public void setCronBeanIntoSchedule() {
		List<Quartz> list = quartzService.getAllQuartz();
		String message ="";
		int  i =1;
		if (list != null && list.size() > 0) {
			for (Quartz quartz : list) {
				message+="("+i+")";
				message+=config(quartz);
				i++;
			}
			logger.info("定时注入触发器,任务,实体类,时间："+message);
		}
	}

	/**
	 * @param quartz
	 */
	private String config(Quartz quartz) {
		String msg="";
		try {
		    CronTriggerBean trigger = (CronTriggerBean)this.schedule.getTrigger(quartz.getTriggername(), Scheduler.DEFAULT_GROUP);
			if (trigger == null) {// create job
				if(quartz.getState().equals("1")){
					msg=createJobInsertSchedule(quartz)?"create new scheduler:"+quartz.getTriggername()+","+quartz.getCronexpression():"fail of create new scheduler :"+quartz.getTriggername();
				}else{
					msg="scheduler:"+quartz.getTriggername()+" state is forbidden";
				}
			} else {// modify job
				 msg=changeJobOfSchedule(quartz,trigger)?"change scheduler as to : "+quartz.getTriggername()+","+quartz.getCronexpression():"delete scheduler: "+quartz.getTriggername();
			}
		} catch (SchedulerException e) {
			logger.error(e.getMessage(),e);
		}
		return msg;
	}

	/**
	 * @param quartz
	 * @param trigger
	 */
	private boolean changeJobOfSchedule(Quartz quartz, CronTriggerBean trigger) {
		if(quartz.getState().equals("1")){
			if(!quartz.getCronexpression().equalsIgnoreCase(trigger.getCronExpression())){//chanage
				try {
					trigger.setCronExpression(quartz.getCronexpression());
					//refesh
					this.schedule.rescheduleJob(quartz.getTriggername(), Scheduler.DEFAULT_GROUP, trigger);
					logger.info("改变cronExpression,time:"+new Date());
					return true;
				} catch (Exception e) {
					logger.error(e.getMessage(),e);
				}
					
			}
		}else{//delete
			try {
				this.schedule.pauseTrigger(trigger.getName(), Scheduler.DEFAULT_GROUP);
				this.schedule.unscheduleJob(trigger.getName(), Scheduler.DEFAULT_GROUP);// 移除触发器
				this.schedule.deleteJob(trigger.getJobName(), Scheduler.DEFAULT_GROUP);// 删除任务
				return false;
			} catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			
		}
		return false;
	}


	/**
	 * @param quartz
	 */
	private boolean createJobInsertSchedule(Quartz quartz) {
		MethodInvokingJobDetailFactoryBean jobdetail = new MethodInvokingJobDetailFactoryBean();
		try {
			if(quartz.getIsspringbean().equals("1")){
				jobdetail.setTargetObject(this.applicationContext.getBean(quartz.getTargetobject()));
			
			}else{
				jobdetail.setTargetObject(Class.forName(quartz.getTargetobject()).newInstance());
			}
			jobdetail.setTargetMethod(quartz.getMethodname());
			jobdetail.setName(quartz.getJobdetailname());
			jobdetail.setConcurrent(quartz.getConcurrent().equals("1"));
			jobdetail.afterPropertiesSet();// 将管理Job类提交到计划管理类
			
			JobDetail jobDetail = jobdetail.getObject();
			jobDetail.setName(quartz.getJobdetailname());
			this.schedule.addJob(jobDetail, true);// 将Job添加到管理类
			
			CronTriggerBean trigger = new CronTriggerBean();
			trigger.setCronExpression(quartz.getCronexpression());
			trigger.setName(quartz.getTriggername());
			trigger.setJobDetail(jobDetail);
			trigger.setJobName(quartz.getJobdetailname());
			this.schedule.scheduleJob(trigger);
			this.schedule.rescheduleJob(quartz.getTriggername(), Scheduler.DEFAULT_GROUP, trigger);
			logger.info("one trigger job insert into scheduler time is:"+quartz.getCronexpression());
			return true;
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
			return false;
		}
	}
}
